﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System.Collections.Specialized;
using FantasyWereld.Common;
using System.Diagnostics;
using Windows.Storage;
using Windows.Data.Xml.Dom;

// The data model defined by this file serves as a representative example of a strongly-typed
// model that supports notification when members are added, removed, or modified.  The property
// names chosen coincide with data bindings in the standard item templates.
//
// Applications may use this model as a starting point and build on it, or discard it entirely and
// replace it with something appropriate to their needs.

namespace FantasyWereld.Data
{
    /// <summary>
    /// Base class for <see cref="NavDataItem"/> and <see cref="NavDataGroup"/> that
    /// defines properties common to both.
    /// </summary>
    [Windows.Foundation.Metadata.WebHostHidden]
    public abstract class NavDataCommon : FantasyWereld.Common.BindableBase
    {
        private static Uri _baseUri = new Uri("ms-appx:///");

        public NavDataCommon(String uniqueId, String title, String imagePath, int count, String newsTitle, String newsContent, int newsIndex, String newsDate, String newsLink)
        {
            this._uniqueId = uniqueId;
            this._title = title;
            this._imagePath = imagePath;
            this._count = count;
            this._newsContent = newsContent;
            this._newsDate = newsDate;
            this._newsLink = newsLink;
            this._newsTitle = newsTitle;
            this._newsIndex = newsIndex;
        }

        private string _uniqueId = string.Empty;
        public string UniqueId
        {
            get { return this._uniqueId; }
            set { this.SetProperty(ref this._uniqueId, value); }
        }

        private string _title = string.Empty;
        public string Title
        {
            get { return this._title; }
            set { this.SetProperty(ref this._title, value); }
        }

        private ImageSource _image = null;
        private String _imagePath = null;
        public ImageSource Image
        {
            get
            {
                if (this._image == null && this._imagePath != null)
                {
                    this._image = new BitmapImage(new Uri(NavDataCommon._baseUri, this._imagePath));
                }
                return this._image;
            }

            set
            {
                this._imagePath = null;
                this.SetProperty(ref this._image, value);
            }
        }

        public void SetImage(String path)
        {
            this._image = null;
            this._imagePath = path;
            this.OnPropertyChanged("Image");
        }

        public override string ToString()
        {
            return this.Title;
        }
        
        private int _count = 0;
        public int Count
        {
            get { return this._count; }
            set { this.SetProperty(ref this._count, value); }
        }

        private string _newsContent = string.Empty;
        public string NewsContent
        {
            get { return this._newsContent; }
            set { this.SetProperty(ref this._newsContent, value); }
        }

        private string _newsDate = string.Empty;
        public string NewsDate
        {
            get { return this._newsDate; }
            set { this.SetProperty(ref this._newsDate, value); }
        }

        private string _newsLink = string.Empty;
        public string NewsLink
        {
            get { return this._newsLink; }
            set { this.SetProperty(ref this._newsLink, value); }
        }

        private int _newsIndex = 0;
        public int NewsIndex
        {
            get { return this._newsIndex; }
            set { this.SetProperty(ref this._newsIndex, value); }
        }

        private string _newsTitle = string.Empty;
        public string NewsTitle
        {
            get { return this._newsTitle; }
            set { this.SetProperty(ref this._newsTitle, value); }
        }

        private bool _showNew = false;
        public bool ShowNew
        {
            get { return this._showNew; }
            set { this.SetProperty(ref this._showNew, value); }
        }

    }

    /// <summary>
    /// Generic group data model.
    /// </summary>
    public class NavDataGroup : NavDataCommon
    {
        public NavDataGroup(String uniqueId, String title, String imagePath, int count, String newsTitle, String newsContent, int newsIndex, String newsDate, String newsLink)
            : base(uniqueId, title, imagePath, count, newsTitle, newsContent, newsIndex, newsDate, newsLink)
        {
        }

    }

    /// <summary>
    /// Creates a collection of groups and items with hard-coded content.
    /// 
    /// NavDataSource initializes with placeholder data rather than live production
    /// data so that Nav data is provided at both design-time and run-time.
    /// </summary>
    public sealed class NavDataSource
    {
        public static NavDataSource _NavDataSource = new NavDataSource();

        public NavDataSource()
        {
            Initialize();
        }

        public void Initialize()
        {
            Clear();

            if (Convert.ToBoolean(ApplicationData.Current.RoamingSettings.Values["ShowNews"]))
            {
                XmlDocument newsList = FWDataSource.GetNews;

                if (newsList.ChildNodes.Count > 0)
                {
                    if (newsList.ChildNodes[1].ChildNodes.Count > 0)
                    {
                        int counters = 0;
                        foreach (XmlElement node in newsList.ChildNodes[1].ChildNodes)
                        {
                            var x = node.Attributes;

                            switch (counters)
                            {
                                case 0:
                                    {
                                        var group0 = new NavDataGroup(
                                            Constants.RSSFEED_N_TITLE,
                                            Constants.RSSFEED_N_TITLE,
                                            Constants.RSSFEED_N_IMAGE,
                                            0,
                                            node.ChildNodes[3].InnerText,
                                            node.ChildNodes[0].InnerText,
                                            0,
                                            node.ChildNodes[1].InnerText,
                                            node.ChildNodes[2].InnerText
                                            );
                                        this.AllGroups.Add(group0);
                                        break;
                                    }
                            }
                            counters++;
                            break;
                        }
                    }
                }
            }

            var group1 = new NavDataGroup(
                Constants.RSSFEED_R_TITLE,
                Constants.RSSFEED_R_TITLE,
                Constants.RSSFEED_R_IMAGE,
                FWDataSource.NrOfReviews,
                "", "", 0, "", "");
            this.AllGroups.Add(group1);

            var group2 = new NavDataGroup(
                Constants.BOOKFEED_TITLE,
                Constants.BOOKFEED_TITLE,
                Constants.BOOKFEED_BD_IMAGE,
                FWDataSource.NrOfBooks,
                "", "", 0, "", "");
            this.AllGroups.Add(group2);

            var group3 = new NavDataGroup(
                Constants.RSSFEED_IV_TITLE,
                Constants.RSSFEED_IV_TITLE,
                Constants.RSSFEED_IV_IMAGE,
                FWDataSource.NrOfInterviews,
                "", "", 0, "", "");
            this.AllGroups.Add(group3);

            var group4 = new NavDataGroup(
                Constants.RSSFEED_GB_TITLE,
                Constants.RSSFEED_GB_TITLE,
                Constants.RSSFEED_GB_IMAGE,
                FWDataSource.NrOfGastblogs,
                "", "", 0, "", "");
            this.AllGroups.Add(group4);

            var group5 = new NavDataGroup(
                Constants.RSSFEED_AR_TITLE,
                Constants.RSSFEED_AR_TITLE,
                Constants.RSSFEED_AR_IMAGE,
                FWDataSource.NrOfArtikelen,
                "", "", 0, "", "");
            this.AllGroups.Add(group5);

            var group6 = new NavDataGroup(
                Constants.RSSFEED_SC_TITLE,
                Constants.RSSFEED_SC_TITLE,
                Constants.RSSFEED_SC_IMAGE,
                FWDataSource.NrOfSchrijven,
                "", "", 0, "", "");
            this.AllGroups.Add(group6);

            var group7 = new NavDataGroup(
                Constants.RSSFEED_OR_TITLE,
                Constants.RSSFEED_OR_TITLE,
                Constants.RSSFEED_OR_IMAGE,
                FWDataSource.NrOfOverigeRecensies,
                "", "", 0, "", "");
            this.AllGroups.Add(group7);

            var group8 = new NavDataGroup(
                Constants.AUTHORFEED_TITLE,
                Constants.AUTHORFEED_TITLE,
                Constants.AUTHORFEED_IMAGE,
                FWDataSource.NrOfAuthors,
                "", "", 0, "", "");
            this.AllGroups.Add(group8);

            var group9 = new NavDataGroup(
                Constants.SHORTSTORYFEED_TITLE,
                Constants.SHORTSTORYFEED_TITLE,
                Constants.SHORTSTORYFEED_IMAGE,
                FWDataSource.NrOfStories,
                "", "", 0, "", "");
            this.AllGroups.Add(group9);
        }
        
        private ObservableCollection<NavDataGroup> _allGroups = new ObservableCollection<NavDataGroup>();
        public ObservableCollection<NavDataGroup> AllGroups
        {
            get { return this._allGroups; }
        }

        public void Clear()
        {
            if (_allGroups != null)
                _allGroups.Clear();
        }

        public static IEnumerable<NavDataGroup> GetGroups(string uniqueId)
        {
            if (!uniqueId.Equals("AllGroups")) throw new ArgumentException("Only 'AllGroups' is supported as a collection of groups");

            return _NavDataSource.AllGroups;
        }

        public static IEnumerable<NavDataGroup> GetAllGroups()
        {
            return _NavDataSource.AllGroups;
        }

        public static NavDataGroup GetGroup(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _NavDataSource.AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public void AddGroup(NavDataGroup navGroup)
        {
            this.AllGroups.Add(navGroup);
        }

        public void AddGroup(NavDataGroup navGroup, int index)
        {
            this.AllGroups.Insert(index, navGroup);
        }

        public void Remove(NavDataGroup navGroup)
        {
            this.AllGroups.Remove(navGroup);
        }

    }
}
